#include "ws2812b_dev.h"
#include "system/includes.h"
#include "asm/ledc.h"

void ledc_init(const struct ledc_platform_data *arg);
void ledc_rgb_to_buf(u8 r, u8 g, u8 b, u8 *buf, int idx);
void ledc_send_rgbbuf_isr(u8 index, u8 *rgbbuf, u32 led_num, u16 again_cnt);

const struct ledc_platform_data my_ledc0_data = {
    .index = 0,
    .port = IO_PORT_DP,
    .idle_level = 0,
    .out_inv = 0,
    .bit_inv = 1,
    .t_unit = t_42ns,
    .t1h_cnt = 24,
    .t1l_cnt = 7,
    .t0h_cnt = 7,
    .t0l_cnt = 24,
    .t_rest_cnt = 20000,
    .cbfun = NULL,
};



// 定义像素点的结构体
typedef struct
{
    unsigned char r; // 红色分量
    unsigned char g; // 绿色分量
    unsigned char b; // 蓝色分量
} Pixel;

/***********************************************************************************************
 *                      接口替换区
 ***********************************************************************************************/
#define led_init() ledc_init(&my_ledc0_data)
#define led_send_rgbbuf(buf, num) ledc_send_rgbbuf_isr(0, buf, num, 1)
#define led_rgb_to_buf(r, g, b, buf, idx) ledc_rgb_to_buf(r, g, b, buf, idx)

// 设置点的颜色函数
// 写缓存
void setPixelColor(Pixel pixels[WIDTH][HEIGHT], u8 x, u8 y, unsigned char r, unsigned char g, unsigned char b)
{
    // 检查坐标是否合法
    if (x < 0 || x >= WIDTH || y < 0 || y >= HEIGHT)
    {
        printf("Invalid coordinates!\n");
        return;
    }

    // 设置像素点的颜色
    pixels[x][y].r = r;
    pixels[x][y].g = g;
    pixels[x][y].b = b;
}

/// @brief 读屏幕颜色缓存
/// @param pixels 需要的的缓存
/// @param color 用于存放读出来的缓存
void get_color(Pixel pixels[WIDTH][HEIGHT], u8 color[WIDTH * HEIGHT][3])
{
    int index = 0;
    for (u8 i = 0; i < HEIGHT; ++i)
    {
        // 奇数行
        if (i % 2 == 0)
        {
            for (int j = 0; j < WIDTH; j++)
            {
                color[index][0] = pixels[j][i].g;
                color[index][1] = pixels[j][i].r;
                color[index][2] = pixels[j][i].b;
                index++;
            }
        }
        // 偶数行
        else
        {
            for (int j = WIDTH - 1; j >= 0; j--)
            {
                color[index][0] = pixels[j][i].g;
                color[index][1] = pixels[j][i].r;
                color[index][2] = pixels[j][i].b;
                index++;
            }
        }
    }
}

//          横轴为长  纵轴为宽
//             长      宽
static Pixel pixels[WIDTH][HEIGHT] = {0}; // 缓存区
static u8 color[WIDTH * HEIGHT][3] __attribute__((aligned(4))) = {0};

void led_screen_test()
{
    printf("led init");
    // 初始化功能
    led_init();

    u8 x = 0;
    u8 y = 0;
    u8 rgb[3] = {255, 0, 0};
    // 设置点的颜色
    setPixelColor(pixels, x, y, rgb[0], rgb[1], rgb[2]);
    setPixelColor(pixels, x + 1, y + 1, rgb[0], rgb[1], rgb[2]);
    setPixelColor(pixels, x + 2, y + 2, rgb[0], rgb[1], rgb[2]);
    // 获取点的颜色并打印
    for (int i = 0; i < HEIGHT; ++i)
    {
        // printf("\n %d  ", i);
        for (int j = 0; j < WIDTH; ++j)
        {
            // printf("[%d,%d] (%d %d %d)",
            //    j, i, pixels[j][i].r, pixels[j][i].g, pixels[j][i].b);
        }
    }
    // 将像素颜色值转为可以传的值
    get_color(pixels, color);

    for (u8 i = 0; i < WIDTH * HEIGHT; ++i)
    {
        // printf("i = %d R:%d  G:%d  B:%d ", i, color[i][0], color[i][1], color[i][2]);
    }
    printf("\n");

    show_color();
}

/// @brief 设置单个像素点的颜色
/// @param x
/// @param y
/// @param pixel_color 颜色值 {r, g, b}
void paint_pixels(u8 x, u8 y, u8 *pixel_color)
{
    setPixelColor(pixels, x, y, pixel_color[0], pixel_color[1], pixel_color[2]);
    get_color(pixels, color);
}

void show_color()
{
    // for (u8 i = 0; i < WIDTH * HEIGHT; ++i)
    // {
        // printf("i = %d R:%d  G:%d  B:%d ", i, color[i][0], color[i][1], color[i][2]);
    // }
    // printf("\n");
    ledc_send_rgbbuf(0, &color[0][0], 48, 0);
}
void updata_screen_color(u8 (*color_data)[3])
{

    for (u8 line = 0; line < 8; line++)
    {
        if (line % 2 == 0)
        {
            for (u8 i = 0; i < 6; i++)
            {
                color[line * 6 + i][0] = color_data[line * 6 + i][0];
                color[line * 6 + i][1] = color_data[line * 6 + i][1];
                color[line * 6 + i][2] = color_data[line * 6 + i][2];
            }
        }
        else
        {
            for (u8 i = 0; i < 6; i++)
            {
                color[line * 6 + i][0] = color_data[line * 6 + 5 - i][0];
                color[line * 6 + i][1] = color_data[line * 6 + 5 - i][1];
                color[line * 6 + i][2] = color_data[line * 6 + 5 - i][2];
            }
        }
    }

    show_color();
}

/* void updata_screen_color(u8 (*color_data)[3], u8 line)
{
    if (line % 2 == 0)
    {
        for (u8 i = 0; i < 48; i++)
        {
            // printf("%d %d %d ", color_data[i][0], color_data[i][1], color_data[i][2]);

            color[line * 6 + i][0] = color_data[i][0];
            color[line * 6 + i][1] = color_data[i][1];
            color[line * 6 + i][2] = color_data[i][2];
        }
    }
    else
    {
        // for (int i = 5; i >= 0; i--)
        for (u8 i = 0; i < 48; i++)
        {
            // printf("%d %d %d ", color_data[i][0], color_data[i][1], color_data[i][2]);

            color[line * 6 + i][0] = color_data[5 - i][0];
            color[line * 6 + i][1] = color_data[5 - i][1];
            color[line * 6 + i][2] = color_data[5 - i][2];
        }
    }

    if (line == 7)
    {
        show_color();
    }
} */
